package com.zkthink.ceres.promotion.service.impl;

import com.fasterxml.jackson.databind.ser.Serializers;
import com.zkthink.base.R;
import com.zkthink.ceres.promotion.dao.PromotionApplyInfoMapper;
import com.zkthink.ceres.promotion.dao.PromotionStatMapper;
import com.zkthink.ceres.promotion.dto.*;
import com.zkthink.ceres.promotion.entity.Promotion;
import com.zkthink.ceres.promotion.entity.PromotionApplyInfo;
import com.zkthink.ceres.promotion.entity.PromotionStat;
import com.zkthink.ceres.promotion.entity.TenantPromotionApplyInfo;
import com.zkthink.ceres.promotion.enums.PromotionAuditStatusEnum;
import com.zkthink.ceres.promotion.service.PromotionApplyInfoService;
import com.zkthink.ceres.promotion.service.PromotionStatService;
import com.zkthink.base.service.SuperServiceImpl;

import com.zkthink.ceres.store.entity.Store;
import com.zkthink.ceres.store.service.StoreService;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.database.mybatis.conditions.Wraps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 业务实现类
 * 
 * </p>
 *
 * @author JustArgo
 * @date 2020-06-30
 */
@Slf4j
@AllArgsConstructor
@Service
public class PromotionStatServiceImpl extends SuperServiceImpl<PromotionStatMapper, PromotionStat> implements PromotionStatService {

    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM-dd");

    private PromotionApplyInfoMapper promotionApplyInfoMapper;

    private StoreService storeService;

    @Override
    public void addPromotionStat(PromotionStat promotionStat) {
        baseMapper.insert(promotionStat);
    }

    @Override
    public R<PromotionStatDTO> getPromotionStatDetail(Long promotionId) {
        if(promotionId==null || promotionId==0){
            return R.fail("活动id不能为空");
        }

        String currentTenant = BaseContextHandler.getTenant();
        BaseContextHandler.setTenant("");
        PromotionStatDTO promotionStatDTO = new PromotionStatDTO();

        Long tradeAmount = 0L;
        Integer tradeOrderCount = 0;
        Integer tradeUserCount = 0;
        Integer tradeTenantCount = 0;
        Integer tradeProductCount = 0;

        Set<Long> midSet = new HashSet<Long>();
        Set<String> tenantCodeSet = new HashSet<String>();
        Map<String,Long> tenantAmountMap = new HashMap<String,Long>();
        Map<String,String> tenantStoreNameMap = new HashMap<String,String>();

        List<PromotionStat> promotionStatList = baseMapper.selectList(Wraps.<PromotionStat>lbQ().eq(PromotionStat::getPromotionId,promotionId));
        for(PromotionStat ps:promotionStatList){
            if(ps.getIsPayed()==1){
                Long orderSum = ps.getOrderSum();
                tradeAmount += orderSum;
                tradeOrderCount += 1;
                if(!midSet.contains(ps.getMid())){
                    tradeUserCount += 1;
                    midSet.add(ps.getMid());
                }
                if(tenantAmountMap.get(ps.getTenantCode())==null){
                    tenantAmountMap.put(ps.getTenantCode(),0L);
                }
                Long oldAmount = tenantAmountMap.get(ps.getTenantCode());
                tenantAmountMap.put(ps.getTenantCode(),oldAmount+orderSum);
                tenantStoreNameMap.put(ps.getTenantCode(),ps.getStoreName());
            }
        }

        List<PromotionApplyInfo> applyInfoList = promotionApplyInfoMapper.selectList(Wraps.<PromotionApplyInfo>lbQ().eq(PromotionApplyInfo::getPromotionId,promotionId)
                .eq(PromotionApplyInfo::getStatus, PromotionAuditStatusEnum.APPLY_SUCCESS.getCode()));
        for(PromotionApplyInfo info:applyInfoList){
            tradeProductCount += info.getProductIds().split(",").length;
            tradeTenantCount += 1;
        }

        promotionStatDTO.setTradeAmout(tradeAmount);
        promotionStatDTO.setTradeOrderCount(tradeOrderCount);
        promotionStatDTO.setTradeUserCount(tradeUserCount);
        promotionStatDTO.setTradeTenantCount(tradeTenantCount);
        promotionStatDTO.setTradeProductCount(tradeProductCount);

        List<PromotionStatDayDTO> dayDTOList = new ArrayList<>();

        LocalDateTime statDay = LocalDateTime.now();
        for(int i=0;i<7;i++){
            PromotionStatDayDTO dayDTO = new PromotionStatDayDTO();
            dayDTO.setStatDay(dateTimeFormatter.format(statDay));
            statDay = statDay.minusDays(1);
            dayDTOList.add(dayDTO);
        }
        Collections.reverse(dayDTOList);

        Map<String,Long> tradeAmountMap = new HashMap<String,Long>();
        for(PromotionStat ps:promotionStatList){
            String orderDayStr = dateTimeFormatter.format(ps.getCreateTime());
            if(tradeAmountMap.get(orderDayStr)==null){
                tradeAmountMap.put(orderDayStr,0L);
            }
            Long oldAmount = tradeAmountMap.get(orderDayStr);
            tradeAmountMap.put(orderDayStr,oldAmount+ps.getOrderSum());
        }

        for(PromotionStatDayDTO statDayDTO:dayDTOList){
            Long statAmount = tradeAmountMap.get(statDayDTO.getStatDay());
            if(statAmount==null){
                statAmount = 0L;
            }
            statDayDTO.setTradeAmount(statAmount);
        }

        promotionStatDTO.setPromotionStatDayDTOList(dayDTOList);

        //对商家的交易额进行排序
        List<Map.Entry<String,Long>> entryList = new ArrayList<>(tenantAmountMap.entrySet());
        Collections.sort(entryList, new Comparator<Map.Entry<String, Long>>() {
            @Override
            public int compare(Map.Entry<String, Long> o1, Map.Entry<String, Long> o2) {
                return o2.getValue().compareTo(o1.getValue());
            }
        });
        if(entryList.size()>10){
            entryList = entryList.subList(0,10);
        }
        List<PromotionTenantRankDTO> rankDTOList = new ArrayList<>();
        for(Map.Entry<String,Long> entry:entryList){
            PromotionTenantRankDTO rankDTO = new PromotionTenantRankDTO();
            rankDTO.setStoreName(tenantStoreNameMap.get(entry.getKey()));
            rankDTO.setTenantCode(entry.getKey());
            rankDTO.setTradeAmount(entry.getValue());
            rankDTOList.add(rankDTO);
        }

        promotionStatDTO.setPromotionTenantRankDTOList(rankDTOList);

        BaseContextHandler.setTenant(currentTenant);

        return R.success(promotionStatDTO);
    }

    @Override
    public R<PromotionTenantStatDTO> findTenantStatDetail(Long promotionId, Integer pageIndex, Integer pageSize) {
        if(promotionId==null || promotionId==0){
            return R.fail("活动id不能为空");
        }

        String currentTenant = BaseContextHandler.getTenant();
        BaseContextHandler.setTenant("");
        PromotionTenantStatDTO tenantStatDTO = new PromotionTenantStatDTO();

        List<TenantPromotionApplyInfo> applyInfoList = promotionApplyInfoMapper.selectListWithTenant(promotionId,PromotionAuditStatusEnum.APPLY_SUCCESS.getCode());

        tenantStatDTO.setTotal(applyInfoList.size());

        int start = (pageIndex - 1) * pageSize;
        int end = pageIndex * pageSize;

        if(start>applyInfoList.size()){
            tenantStatDTO.setStatItemDTOList(new ArrayList<>());
        }else{
            if(end>applyInfoList.size()){
                end = applyInfoList.size();
            }
            applyInfoList = applyInfoList.subList(start,end);
        }

        List<PromotionTenantStatItemDTO> itemDTOList = new ArrayList<>();

        for(TenantPromotionApplyInfo applyInfo:applyInfoList){
            List<PromotionStat> promotionStatList = baseMapper.selectList(Wraps.<PromotionStat>lbQ().eq(PromotionStat::getPromotionId,promotionId)
                                                                            .eq(PromotionStat::getTenantCode,applyInfo.getTenantCode()));
            String storeName = "";
            Long tradeAmount = 0L;
            Integer tradeOrderCount = 0;
            Integer tradeProductCount = applyInfo.getProductIds().split(",").length;
            Set<Long> midSet = new HashSet<Long>();
            Set<Long> totalMidSet = new HashSet<Long>();
            for(PromotionStat ps:promotionStatList){
                totalMidSet.add(ps.getMid());
                if(ps.getIsPayed()==1){
                    Long orderSum = ps.getOrderSum();
                    tradeAmount += orderSum;
                    tradeOrderCount += 1;
                    midSet.add(ps.getMid());
                }
            }

            if(promotionStatList.size()==0){
                Store store = storeService.findByTenantCode(applyInfo.getTenantCode());
                if(store!=null){
                    storeName = store.getStoreName();
                }
            }else{
                storeName = promotionStatList.get(0).getStoreName();
            }

            PromotionTenantStatItemDTO itemDTO = new PromotionTenantStatItemDTO();
            itemDTO.setTenantCode(applyInfo.getTenantCode());
            itemDTO.setStoreName(storeName);
            itemDTO.setTradeAmount(tradeAmount);
            itemDTO.setOrderCount(tradeOrderCount);
            itemDTO.setPayedUserCount(midSet.size());
            itemDTO.setPricePerUser(midSet.size()>0?tradeAmount/midSet.size():0);
            itemDTO.setTradeProductCount(tradeProductCount);
            itemDTO.setTradeUserCount(totalMidSet.size());
            itemDTOList.add(itemDTO);
        }

        tenantStatDTO.setStatItemDTOList(itemDTOList);

        BaseContextHandler.setTenant(currentTenant);

        return R.success(tenantStatDTO);
    }

    @Override
    public void payOrder(String orderCode) {
        String currentTenant = BaseContextHandler.getTenant();
        BaseContextHandler.setTenant("");
        PromotionStat updateStat = new PromotionStat();
        updateStat.setOrderCode(orderCode);
        updateStat.setIsPayed(1);
        baseMapper.update(updateStat,Wraps.<PromotionStat>lbQ().eq(PromotionStat::getOrderCode,orderCode));
        BaseContextHandler.setTenant(currentTenant);
    }
}
